module LESSON-02-A
syntax Color ::= Yellow() | Blue()
syntax Fruit ::= Banana() | Blueberry()
syntax Color ::= colorOf(Fruit) [function]
rule colorOf(Banana()) => Yellow()
rule colorOf(Blueberry()) => Blue()
endmodule
kompile lesson-02-a.kbanana.color with:colorOf(Banana())
krun banana.color<k> Yellow() ~> . </k>
krun -cPGM='colorOf(Banana())'
krun.syntax, followed by a sort, and the operator ::=.Yellow(), Blue(), Banana(), and Blueberry().[function].colorOf(Fruit)You can define equivalent programs in multiple ways:
syntax Color ::= Yellow()
syntax Color ::= Blue()
syntax Fruit ::= Banana()
syntax Fruit ::= Blueberry()
syntax Color ::= colorOf(Fruit) [function]
syntax Color ::= Yellow() | Blue() | colorOf(Fruit) [function]
syntax Fruit ::= Banana() | Blueberry()
All variations produce the same output when compiled and executed.
=>.rule colorOf(Banana()) => Yellow()
F.syntax Container ::= Jar(Fruit)
rule contentsOfJar(Jar(F)) => F
F matches Apple() or Pear().syntax Fruit ::= Blackberry() | Kiwi()
rule colorOf(Blackberry()) => Black()
rule colorOf(Kiwi()) => Green()
lesson-02-a.k.krun to check if the fruits are correctly handled by the colorOf function.syntax Outfit ::= outfit(Hat, Shirt, Pants, Shoes)
syntax Color ::= Black() | White()
syntax Boolean ::= true() | false()
syntax Boolean ::= outfitMatching(Outfit) [function]
rule outfitMatching(outfit(C, C, C, C)) => true()
Understanding K’s Parsing Mechanisms and Syntax Definitions
BNF Notation: An Overview
1. Definition of BNF:
2. Purpose:
3. Components of BNF:
BNF consists of several key components, which include:
Non-terminal Symbols: These are variables that can be expanded into one or more sequences of terminal symbols or other non-terminal symbols. They are usually represented by uppercase letters or descriptive names.
Terminal Symbols: These are the actual symbols from which the language is constructed. They can be keywords, operators, literals, or other basic elements of the language. Terminal symbols are typically enclosed in quotes or are represented in lowercase.
Production Rules: These rules define how non-terminal symbols can be replaced or expanded into sequences of symbols. Each production rule is written in the form:
<non-terminal> ::= <expression>
Here, ::= means “can be replaced by.” The expression on the right can consist of non-terminals, terminals, or a combination of both.
Alternatives: Multiple expansions for a non-terminal can be specified using the vertical bar (|). For example:
<expression> ::= <term> | <term> '+' <expression>
4. Example of BNF:
Here’s a simple example of BNF to define basic arithmetic expressions:
<expression> ::= <term> | <term> '+' <expression> | <term> '-' <expression>
<term> ::= <factor> | <factor> '*' <term> | <factor> '/' <term>
<factor> ::= <number> | '(' <expression> ')'
<number> ::= <digit> | <digit> <number>
<digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
Explanation of the Example:
<expression> can be a single <term>, or a <term> followed by either a + or - followed by another <expression>.<term> can be a single <factor>, or a <factor> followed by either a * or / followed by another <term>.<factor> can be a <number> or an <expression> enclosed in parentheses.<number> is defined as one or more digits (<digit>), and <digit> is defined as any single numeral from 0 to 9.5. Advantages of BNF:
6. Variants of BNF:
module LESSON-03-A
syntax Boolean ::= "true" | "false"
| "!" Boolean [function]
| Boolean "&&" Boolean [function]
| Boolean "^" Boolean [function]
| Boolean "||" Boolean [function]
endmodule
&&, ||, !, etc.) in a simple grammar.Example:
syntax Color ::= "Yellow" "(" ")" | "Blue" "(" ")"
kastProgram: true && false
Command: kast --output kore and.bool
KORE Output: AST representation of the parsed program.
inj{SortBoolean{}, SortKItem{}}(
Lbl'UndsAnd-And-UndsUnds'LESSON-03-A'Unds'Boolean'Unds'Boolean'Unds'Boolean{}(
Lbltrue'Unds'LESSON-03-A'Unds'Boolean{}(),
Lblfalse'Unds'LESSON-03-A'Unds'Boolean{}()
)
)
Ambiguity Example:
true && false || false(true && false) || falsetrue && (false || false)Solution: Use brackets to resolve ambiguity in expressions.
module LESSON-03-D
syntax Boolean ::= "true" | "false"
| "(" Boolean ")" [bracket]
| "!" Boolean [function]
| Boolean "&&" Boolean [function]
| Boolean "||" Boolean [function]
endmodule
(true && false) || falsetrue && (false || false)Define more complex lexical syntax using tokens:
syntax Int ::= r"[\\+\\-]?[0-9]+" [token]
Example: C-like integer constants:
syntax IntConstant ::= r"({DecConstant}|{OctConstant}|{HexConstant})({IntSuffix}?)" [token]
Priority Blocks:
true && false || false, && has higher precedence than ||, resulting in the AST being (true && false) || false.Associativity:
true && false && false is parsed as (true && false) && false because && is left-associative.Explicit Priority and Associativity Declarations:
group(_) for organizing related productions and applying priority and associativity to those groups.Prefer/Avoid Attributes:
avoid attribute can be added to a production to disallow it in the event of ambiguity.K’s grammar consists of:
The semantics of K is defined by the sentences within a module.
Module Structure:
Valid Module Names:
FOO, FOO-BAR, foo0, foo0_bar-Baz9Invalid Module Names:
-, -FOO, BAR-, FOO--BARExamples:
Empty Module:
module LESSON-05-A
endmodule
Module with Attributes:
module LESSON-05-B [group(attr1,attr2), private]
endmodule
Module with Sentences:
module LESSON-05-C
syntax Boolean ::= "true" | "false"
syntax Boolean ::= "not" Boolean [function]
rule not true => false
rule not false => true
endmodule
imports <module_name>module LESSON-05-D-1
syntax Boolean ::= "true" | "false"
syntax Boolean ::= "not" Boolean [function]
endmodule
module LESSON-05-D
imports LESSON-05-D-1
rule not true => false
rule not false => true
endmodule
module LESSON-05-E-1
rule not true => false
rule not false => true
endmodule
module LESSON-05-E-2
syntax Boolean ::= "true" | "false"
syntax Boolean ::= "not" Boolean [function]
endmodule
Entry Points:
Default Behavior:
--main-module and --syntax-module can specify modules explicitly.FOO for semantics and FOO-SYNTAX for syntax.requires "filename.k"Example Definition Structure:
colors.k:
module COLORS
syntax Color ::= Yellow()
| Blue()
endmodule
fruits.k:
module FRUITS
syntax Fruit ::= Banana()
| Blueberry()
endmodule
colorOf.k:
requires "fruits.k"
requires "colors.k"
module COLOROF-SYNTAX
imports COLORS
imports FRUITS
syntax Color ::= colorOf(Fruit) [function]
endmodule
module COLOROF
imports COLOROF-SYNTAX
rule colorOf(Banana()) => Yellow()
rule colorOf(Blueberry()) => Blue()
endmodule
Compilation: Use kompile colorOf.k to compile and use the definition as a single module.
SimpleArithmetic.solThis smart contract provides basic arithmetic operations similar to the definitions we created in K.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract SimpleArithmetic {
// Function to add two integers
function add(int a, int b) public pure returns (int) {
return a + b;
}
// Function to subtract two integers
function subtract(int a, int b) public pure returns (int) {
return a - b;
}
// Function to multiply two integers
function multiply(int a, int b) public pure returns (int) {
return a * b;
}
// Function to divide two integers
function divide(int a, int b) public pure returns (int) {
require(b != 0, "Division by zero");
return a / b;
}
// Function to evaluate a boolean expression
function evaluate(bool a, bool b) public pure returns (bool) {
return a && b; // Logical AND
}
// Function to evaluate NOT
function negate(bool a) public pure returns (bool) {
return !a; // Logical NOT
}
}
SimpleArithmetic.solContract Declaration: contract SimpleArithmetic defines a new Solidity smart contract named SimpleArithmetic.
Function Definitions:
add, subtract, multiply, divide).divide function includes a check to prevent division by zero using require.Boolean Operations:
evaluate function implements a logical AND operation.negate function implements a logical NOT operation.solidity-tests.kThis file will contain the necessary K definitions to specify properties for testing the Solidity contract.
module SOLIDITY-TESTS
// Importing necessary modules for Boolean and Arithmetic operations
requires "booleans.k"
requires "arithmetic.k"
// Syntax for Solidity function calls and parameters
syntax FunctionCall ::= "add" "(" Int "," Int ")" [function]
syntax FunctionCall ::= "subtract" "(" Int "," Int ")" [function]
syntax FunctionCall ::= "multiply" "(" Int "," Int ")" [function]
syntax FunctionCall ::= "divide" "(" Int "," Int ")" [function]
syntax FunctionCall ::= "evaluate" "(" Boolean "," Boolean ")" [function]
syntax FunctionCall ::= "negate" "(" Boolean ")" [function]
// Define evaluation rules for testing the smart contract functions
rule evalExpr(add(X, Y)) => X + Y
rule evalExpr(subtract(X, Y)) => X - Y
rule evalExpr(multiply(X, Y)) => X * Y
rule evalExpr(divide(X, Y)) => Y == 0 => "Division by zero" // Handle division by zero case
rule evalExpr(divide(X, Y)) => X / Y
rule evalExpr(evaluate(A, B)) => A && B
rule evalExpr(negate(A)) => not A
endmodule
solidity-tests.kRequires Directive:
requires "booleans.k" and requires "arithmetic.k" include the modules that provide definitions for Boolean and arithmetic operations.Syntax Definitions:
add, subtract, multiply, divide, evaluate, and negate).Evaluation Rules:
rule evalExpr(add(X, Y)) => X + Y indicates that calling add(X, Y) should yield the arithmetic addition of X and Y.Y is zero to prevent division by zero errors.run_tests.shYou can use a simple shell script to compile and run the tests.
#!/bin/bash
# Compile the Solidity contract
echo "Compiling the Solidity contract..."
solc --bin --abi SimpleArithmetic.sol -o build/
# Run the K tests
echo "Running K tests..."
kompile solidity-tests.k --main-module SOLIDITY-TESTS
# Execute the K test with krun
krun result.k
# Add any additional commands to verify the output as necessary
Compile the Solidity Contract:
solc command to compile the SimpleArithmetic.sol contract. This generates binary and ABI files in the build/ directory.Run the K Tests:
kompile.krun.Output Verification:
In this setup, we created a simple Solidity smart contract that performs arithmetic and Boolean operations. We also defined a corresponding K framework for testing the smart contract’s functionality by specifying properties of the operations we implemented.
By executing the K tests, you can ensure that the operations in the Solidity contract behave as expected, and any discrepancies can be identified and addressed. This approach effectively combines smart contract development and formal verification through the K framework.